import config from '@/common/config';
import http from '@/common/http.interceptor';
import { encryptPassword } from '@/common/utils';
// 传参去除空格
import myMixin from '@/common/myMixin.js';

// 支持的请求方式
const supportMethod = ['GET', 'POST'];
// 默认请求方式
const defaultMethod = 'POST';
// 请求函数字典
const methodFnMap = {
  GET: http.get,
  POST: http.post,
};

// 请求字典
const requestMap = new Map();

// 如果请求字典存在相同请求则返回原请求
const getRealRequest = (url, req, iv = '') => {
  const requestKey = encryptPassword(url, iv);
  if (requestMap.has(requestKey)) return requestMap.get(requestKey);
  const p = req().finally(() => {
    requestMap.delete(requestKey);
  });
  requestMap.set(requestKey, p);
  return p;
};

// 根据请求参数签名出偏移量
const signRequestIv = (data = {}) => {
  let iv = '';
  let dataArr = Object.entries(data);
  dataArr = dataArr.sort(([k1], [k2]) => {
    return k1 > k2 ? 1 : k1 < k2 ? -1 : 0;
  });
  for (const [k, v] of dataArr) {
    iv += `&${k}=${v}`;
  }
  return encryptPassword(iv.substring(1), '');
};

// 请求返回状态码非成功处理
const requestErrorHandle = (res = {}, cacheName=false) => {
  const { data: outerData, errMsg } = res;
  if (!outerData) return Promise.reject({ data: { code: 400, message: '请求异常' } });
  if (errMsg === 'request:fail timeout')
    return Promise.reject({ data: { code: 400, message: '请求超时' } });

  const { code, data: innerData } = outerData;
  const isSuccess = code == 0;
  if (cacheName && isSuccess) {
    const storageData = { data: innerData, version: config.clientversion, type: 'apiCache' };
    uni.setStorage({ key: cacheName, data: storageData });
  }

  return res;
};

// 请求函数
const request = (options) => {
  // 传参去除空格
  // if(myMixin&&myMixin.methods.isEmptyNew()&&options&&options.data){
  //   if(!myMixin.methods.isEmptyNew(options.data)){
  //     //Object.entries(): 返回一个对象自身的（不含继承的）所有可遍历（enumerable）属性的键值对的数组
  //     let arr = Object.entries(options.data)
  //     arr.forEach((item,index )=>{
  //       if(myMixin.methods.emptyString(item[1])){
  //         //替换空格
  //         // item[1] = item[1].replace(/\s*/g, "")
  //         //替换空格
  //         item[1] = item[1].replace(/^\s+|\s+$/g, "")
  //       }
  //     })
  //     //Object.fromEntries(): 将一个键值对数组转为对象
  //     options.data = {...Object.fromEntries(arr)}
  //   }
  // }

  const reqIv = signRequestIv(options.data);
  options.data = Object.assign(options.data || {}, { needMemberId: options.needMemberId });
  // 确保请求方式在允许的范围内
  let { method = defaultMethod,cacheName=false } = options;
  method = method.toLocaleUpperCase();
  method = supportMethod.includes(method) ? method : defaultMethod;
  let req = () => http.post(options.url, options.data);
  if(methodFnMap[method]){
    req = () => methodFnMap[method](options.url, options.data);
  }

  const requestPromie = getRealRequest(options.url, req, reqIv);
  return requestPromie.then((res) => requestErrorHandle(res, cacheName));
};

// mg接口调用
const mgRequest = (options = {}, needMemberId = true, cacheName=false) => {
  // options.url = config.baseUrl + options.url;
  // 跨域
  options.url = (config.type == 1 ? '/api/' : config.baseUrl) + options.url;
  return request(Object.assign(options, { needMemberId, cacheName }));
};

// 支付接口调用
const paymentRequest = (options = {}, needMemberId = true, cacheName) => {
  options.url = config.payUrl + options.url;
  return request(Object.assign(options, { needMemberId, cacheName }));
};

// api接口调用
const apiRequst = (options = {}, needMemberId = true, cacheName) => {
  options.url = config.shopApiUrl + options.url;
  return request(Object.assign(options, { needMemberId, cacheName }));
};

export const uniRequest = mgRequest;
export const payRequest = paymentRequest;
export const shopRequst = apiRequst;
